package cn.assumejson.springframework.aop.annotation;

import cn.assumejson.springframework.aop.Advisor;
import cn.assumejson.springframework.aop.aspectj.annotation.AspectJAdvisorFactory;
import cn.assumejson.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder;
import cn.assumejson.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory;
import cn.assumejson.springframework.aop.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import cn.assumejson.springframework.beans.factory.ListableBeanFactory;
import cn.assumejson.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import java.util.List;
import java.util.regex.Pattern;

/**
 * @author Mr. Li
 * @version 1.0
 * @since 1.0 2021/12/6 11:07
 */
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    private List<Pattern> includePatterns;

    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;

    private AspectJAdvisorFactory aspectJAdvisorFactory;

    @Override
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.initBeanFactory(beanFactory);

        if (this.aspectJAdvisorFactory == null) {
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }
        this.aspectJAdvisorsBuilder =
                new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }

    protected boolean isEligibleAspectBean(String beanName) {
        if (this.includePatterns == null) {
            return true;
        } else {
            for (Pattern pattern : this.includePatterns) {
                if (pattern.matcher(beanName).matches()) {
                    return true;
                }
            }
            return false;
        }
    }

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        // 先找到所有Advisor类型的Bean对象
        List<Advisor> advisors = super.findCandidateAdvisors();

        // Build Advisors for all AspectJ aspects in the bean factory.
        // 再从所有切面中解析得到Advisor对象
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

    private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {

        public BeanFactoryAspectJAdvisorsBuilderAdapter(
                ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {

            super(beanFactory, advisorFactory);
        }

        @Override
        protected boolean isEligibleBean(String beanName) {
            return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
        }
    }

}
